Spike Challenge - Predicción de precios de insumos básicos en Chile

En este desafío vamos a ver si somos capaces de predecir el precio de un insumo básico, como la leche, a partir de variables climatológicas y macroeconómicas. No siempre estos datos nos entregan toda la información que nos gustaría, como por ejemplo señales claras del avance de la sequía a lo largo del país, sin embargo, nos permite entender otro tipo de efectos, como movimientos en ciertos sectores de la economía

Autor: Daniel Pereda

0. Cargar paquetes

Paquetes utilizados:

Nota: No cargué todos los paquetes al comienzo para que sea más fácil leer el desarrollo y ver dónde utilicé cada uno.

1. Datos: Precipitaciones, Indicadores Económicos Banco Central

A este no le haré parse_dates ya que hay fechas incorrectas (comentarios en gitter)

2. Análisis de datos. Creación de variables

2.1 EDA

Realiza un análisis exploratorio de la base de datos, ¿Qué puedes decir de los datos, sus distribuciones, valores faltantes, otros? ¿Hay algo que te llame la atención?

2.1.1 Precipitaciones

Por la cantidad de datos ($496$), la granularidad debería ser mensual, con 12 datos por año excepto el 2020 con 4. Hagamos un sanity check

Al ver las distribuciones notamos que los datos tienen sentido, las regiones de la zona norte y centro en donde llueve menos presentan altos nivel de skewness, mientras que las que están más al Sur siguen teniendo cola pero con valores más cercanos a 1.

Finalmente ordenamos por fecha.

2.1.2 Banco Central

Veamos primero la cantidad y el rango de fechas de estos datos, para ver como se compara con el de precipitaciones

Inmediatamente vemos que hay una fecha incorrecta, debemos cambiar el mes "13" por el mes correcto.

Vemos que el único mes faltante es Diciembre, además hubo un problema con la recolección de datos en Noviembre la cual persiste en Diciembre.

Cambiamos ahora la columna "Periodo" a datetime y deslocalizamos para tener consistencia con los datos de precipitación. En caso de existir otra fecha incorrecta, esto nos arrogará un error.

Tenemos datos desde Enero 1970 hasta Diciembre 2020, esto corresponde a $(2020 - 1970 + 1) \times 12 = 612$ datos, pero tenemos 614 filas. Esto significa que tenemos filas duplicadas que tendremos que arreglar.

Notamos que la cantidad de valores nulos en algunas columnas es significativamente alta. Esta es una de las razones por las cuales columnas que deberían ser numéricas son reconocidas como object.

Utilizando el paquete missingno podemos visualizar los valores nulos y ver si hay algún patrón

Efectivamente, la mayoría de los datos se tienen solo desde el año 2013. Tenemos que analizar qué haremos con esto, dependiendo del rango de fechas de nuestro target set precio_leche.csv, correlación entre columnas y resultados del modelo base.

Por último, me llama la atención que la mayoría de los números tienen doble punto $933.369.433$ por lo que tendremos que hacer una limpieza para transformarlos realmente en números.

Por todo lo anterior, no podemos sacar mucha información estadística de los números de este dataset antes de limpiarlo.

Podemos ver que existen datos para "Precio de la onza troy de oro dolaresoz" desde el año 1970 y que tal serie presenta una tendencia. Por otro lado, las demás variables asociadas a Precios parecieran tener baja variación antes del año 2005.

Veamos sus distribuciones haciendo un slicing en tal año.

Vemos que antes del 2005 la distribución es bastante distinta a después del 2005. En caso de que usemos alguna de estas variables en nuestro modelo, tendremos que tener esto en cuenta para elegir el período de tiempo que utilizaremos de entrenamiento.

2.2 Limpieza de datos

Como vimos anteriormente, los datos de precipitaciones están bien. De manera que en esta sección nos enfocaremos en limpiar los datos del banco central.

2.2.1 Duplicados

Eliminamos las 2 filas duplicadas.

Por ahora eliminamos las filas que tienen valores idénticos en todas las columnas, la cantidad de datos totales calza con las que deben ser (612), sin embargo veamos si hay fechas repetidas.

Excelente, no hay fechas repetidas. Podemos dejar la fecha como índice.

2.2.2 Arreglar números

De las primeras dos filas de datos que miramos anteriormente, notamos que habían valores nulos, por lo que si bien todos los indicadores (Imacec, PIB, impuestos, etc) deberían ser numéricos, serán reconocidos como object. Además vemos que los números aparecen con doble punto, si revisamos la página del banco central, vemos que el Imacec tiene valores en torno a los cientos, analogamente para los índices de ventas. Ahora, si cambiamos todos los índices por ejemplo de Imacec de forma consistente, no debería haber diferencia si el valor es 109.690834 o 109690.834 (dependiendo del modelo, podríamos necesitar hacer un cambio de escala o estandarizar los datos, y en caso de no hacerlo sí hay diferencia entre 109 y 109*100).

Las siguientes 2 funciones serán útiles para limpiar los datos y para separar las columnas según estimemos conveniente

Podemos separar las columnas de los datos bancarios en:

Si bien, vamos a repetir mucho código. Esto servirá más adelante para estudiar correlaciones entre variables y target, además de ver como se comportan datos del mismo grupo.

Imacec

PIB

Vemos que los valores no están correctos y parecieran seguir un patrón. A priori no se me ocurre una forma inteligente de arreglar todas las columnas, y aún no sabemos si el tiempo invertido en esto será necesario, por lo que las arreglaré de forma aproximada y más adelante podemos cambiar los números en los quantiles extremos por NaN y reemplazarlos o por interpolación o tomando medias móviles.

INE

Usaremos la misma funciones que para el PIB

Indices

Precios

Otros

Outliers

Finalmente cambiamos los valores que no logré limpiar bien por NaN. Además tomaré los datos solo desde el 2005, por lo comentado anteriormente.

Si el modelo no logra los resultados esperados, tendremos entonces que limpiar mejor los datos.

Esto logra mejorar bastante algunas de las columnas, como las que listamos en "otros"

3. Visualización

3.1 Crear función que permita graficar series históricas de precipitaciones

3.2 Graficar utilizando 3.1

Respuesta: Existe estacionalidad, podemos ver que las precipitaciones son bajas durante el verano, crecen hasta tener máximos en invierno y luego decrecen en primavera. Por otro lado, no se puede ver una tendencia muy marcada, solo en la escala y máximos anuales que se han vuelvos más pequeños y menos habituales que al comienzo de los años 2000.

3.3 Funcion que grafica múltiples series de tiempo

3.4 Región del Maule para distintos años

Respuesta: Podemos concluir que la cantidad de precipitaciones ha disminuído considerablemente durante los últimos 40 años, en 2019 es pŕacticamente la mitad de las precipitaciones en 1982. Por otro lado, podemos ver cómo los máximos ocurren generalmente en el mes de Junio y Agosto.

3.5 Funcion que grafica dos series históricas del PIB

Respuesta: Podemos ver que el PIB Agropecuario y silvicola presenta una estacionalidad marcada, con máximos en verano y mínimos en invierno y sin una tendencia clara. Por otro lado, el PIB de Servicios financieros ha ido aumentando mostrando una tendencia al alza.

Respuesta: A partir de este gráfico, no se ve una relación clara entre ambas series.

4. Tratamiento y creación de variables

Respuesta:

Calcular la correlación entre dos series de tiempo es un tema delicado, podemos ver en nuestras series de tiempo que existe una tendencia (los precios tienen a subir), esto hará que obtengamos correlaciones altas incluso cuando ambas series no tienen una relación real, esto se conoce como relación espuria (página dedicada a mostrar este tipo de relaciones). Por esta razón, veremos la correlación en las diferencias de primer orden, esto remueve la tendencia y nos permite mirar el efecto real.

Para entrenar un modelo, queremos tener variables que estén altamentes correlacionadas con nuestra variable objetivo (teniendo las precauciones mencionadas anteriormente para series de tiempo). Por otro lado, en general no es bueno que las características (features) estén altamente correlacionadas entre ellas, puesto que no estarían aportando información nueva y estarían sesgando el modelo (especialmente a modelos lineales).

Por último, en series de tiempo tenemos dos conceptos interesantes que tienen que ver con autocorrelación y autocorrelación parcial, la primera es la correlación entre $y_{t_1}$ y $y_{t_2}$ con $t_1 < t_2$. La segunda, elimina los efectos de otros períodos y nos permite estudiar el impacto puro de la variable en tiempo $t_1$ para predecir la variable en tiempo $t_2$. Al igual que para la correlación, tenemos que mirar esto en la serie de tiempo estacionaria. Las variables que generamos a partir de esto se conocen como lags y general mejoran el rendimiento de los modelos.

4.1 Datos Banco Central

Primero vemos que las columnas relacionadas a Precios no están correlacionadas entre sí o con el Imacec. Mientras que las columnas del imacec están altamente correlacionadas en su grupo.

Si vieramos las correlaciones en las series no estacionarias, la mayoría de las columnas tienen alta correlación.

Con respecto a las columnas del PIB, vemos que todas están correlacionadas con al menos alguna otra columna

Podríamos escoger a mano qué columnas usar, pero podemos automatizar el proceso y volver a agregar columnas a mano que consideremos importantes si el modelo no es suficientemente bueno.

4.2 Datos Precio leche

Notamos que no hay valores faltantes y los meses están ordenados por lo que podemos pasarlos a sus valores numéricos haciendo un mapping entre los meses y $\{1, ..., 12\}$

Creamos la columna date con el mismo formato de los otros datos insertandola en la posición 0

Merge

4.3 Creación de variables

4.3.1 A partir de Autocorrelación

Con todos los datos del mes $t$ queremos predecir el precio del mes $t+1$, por esta razón, hacemos un shift en -1 a la columna "Precio_leche" y le cambiamos el nombre a "y". Esta variable se transforma en nuestro target.

A partir de la fecha

Dado que el Mes es una feature ordinal cíclica y que no utilizaremos un modelo basados en árboles de decisión, podemos transformar la columna mes a una feature cíclica utilizando funciones trigonométricas, en este caso, como los valores máximos se encuentran a mitad de año, la función $-cos(x)$ nos debería dar buena señal.

Vemos que las 2 features que introdujimos cumplen con estar a distancia constante y ser cíclicas

Trimestre

Esta transformación hace que perdamos un punto, dado que $cos(\frac{2\pi}{3}) = cos(\frac{4\pi}{3}) = 1/2$.

Variables relacionadas al clima

Regiones cercanas tienen alta correlación, por lo que eliminamos algunas.

Variables relacionadas al banco

Consideramos los datos desde el 2013 para ver las correlaciones

Missing values

Modelo

Los precios de la leche tienen una tendencia al alza, dado que los modelos basados en árboles de decisión no son buenos extrapolando, tendremos que utilizar otro tipo de modelos, ya sean lineales, basados en medias moviles autoregresivos u otros.

En este caso, elegí utilizar Prophet que en general tiene buen rendimiento en este tipo de problemas.

En cuanto al set de entrenamiento, tomé uno sin las variables del PIB, la limpieza que hice no fue suficientemente buena por lo que el trade-off de perder datos de los años 1979 a 2013 a cambio de agregar tales columnas impactaba negativamente al modelo.

5.1 Entrenamiento Modelo: Prophet

Revisemos los residuos

5.2 Baseline

Pondremos como modelo baseline uno que entrega como precio para el siguiente mes, el precio del mes actual.

Veamos los resultados del modelo vs modelo baseline por año

5.3 Preguntas y respuestas

Respuesta:

Al ser una serie de tiempo tenemos que hacer una separación temporal. Prophet trae un método de validación cruzada implementado, pero por simplicidad en la comparación con el modelo baseline, preferí separar los datos en ~ 15 años de entrenamiento (177 meses) y ~ 9 (112 meses) de test, esto es, $\approx \frac{2}{3}$ de datos en entrenamiento y $\approx \frac{1}{3}$ en test, lo tomé más grande del 80/20 típico, para ver qué tan robusto era dado que iba a utilizar solo un set de entrenamiento y no validación cruzada.

Por otro lado, se parte del año 1996 con los datos de entrenamiento, porque tenemos features que vienen del Imacec.

Si utilizamos datos del PIB, tendríamos que comenzar en el año 2013, acortando bastante la cantidad de datos. Con más tiempo, podríamos limpiar bien estos datos o hacer un mejor análisis para generar features que nos den más señal, mejorando el modelo.

Respuesta:

Me gustaría tener los siguientes datos adicionales:

Creo que los mismos datos mencionados anteriormente servirían para mejorar las métricas.

Respuesta:

Tiene sentido mirar al error absoluto promedio, pues estamos hablando de precios, por lo que equivocarnos en 10 pesos es 10 veces peor que equivocarnos en 1 peso, en términos de dinero. Por otro lado, este valor por si sólo no nos dice qué tan bueno fue el modelo sin saber su tamaño comparado con los valores del precio de la leche, por lo que también tiene sentido mirar a MAPE. En caso de que para el cliente o aplicación que estamos realizando perder 10 pesos no sea 10 veces peor que perder 1 peso, sino que más, entonces podemos mirar RMSE.

Es bueno tener un modelo dummy base que represente cómo se están prediciendo los precios, sin utilizar algoritmos y modelos. En este caso, podemos pensar en un modelo que da como predicción para el mes siguiente el mismo precio del mes actual. El modelo entregado le gana a este modelo dummy consistentemente desde el año 2012 en las métricas mencionadas anteriormente.

Finalmente, tiene sentido también mirar a los residuos una vez que los transformamos en estacionarios. Si la transformación tiene las características de ruido blanco, entonces el modelo está haciendo predicciones suficientemente buenas con los datos entregados, si no, aún hay espacio para mejorar. En el caso del modelo actual, aún hay un pequeño espacio de mejora, podemos intentar mejorar solo con hiperparámetros utilizando optuna o similares.

Respuesta

El modelo que acabamos de crear nos da una estimación del precio de la leche, lo que está relacionado con la demanda por tales productos. Esto puede ayudar a empresas o personas naturales que quieren planificar sus pedidos de leche.

Los modelos se series de tiempo tienen un gran impacto en el día a día, un problema que conozco es en energías renovables y cómo implementarlas en los mercados, en particular, hay un tipo de mercado en donde cada generador de energía (convencional o renovable) entrega sus pujas (bids) a un organismo central e independiente, el cual asigna las cantidades a producir y precio tales que minimicen el costo total de la red. Los generadores de energía eligen las pujas de manera de ganar la mayor cantidad de dinero posible (si dan un precio muy alto, el organismo central les asignará 0 producción) resolviendo un problema de optimización. Una de las dificultades que tienen los productores de energías renovables en estos mercados es que su capacidad de producción no es determinista, un modelo de este tipo puede ayudar elegir un valor y transformar el problema en determinista, o acotar el espacio en donde vive la capacidad, para que luego el problema de optimización pueda ser resuelto más fácilmente. En este sentido, estaríamos ayudando a introducir generadores de energía renovables al mercado y por lo tanto combatiendo el cambio climático.

Podemos crear modelos que tengan que ver directamente con el cambio climático, por ejemplo viendo como han disminuído las precipitaciones durante los últimos años. La gracia es al agregarle variables al modelo, podemos ver su impacto en la disminución de precipitaciones, luego generar un análisis estadístico cuidadoso para detectar la importancia de estas variables positiva o negativa, por ejemplo variables asociadas a emisiones de gases de efecto invernadero deberían tener un impacto negativo, y por lo tanto, uno puede entregar recomendaciones con respecto a cómo mejorar y dar predicciones sobre cómo empeorarán las condiciones en caso de no tomar acciones.

¡Muchas gracias por tu tiempo y por la oportunidad. Que tengas un buen día!